import qualified Data.Set as Set

data Direction = E
               | SE
               | SW
               | W
               | NW
               | NE
                 deriving (Show, Eq)

type Path = [Direction]
type Position = (Int, Int)

type Record = Set.Set Position

parseDirection :: String -> (String, Direction)
parseDirection (s:ss) 
    | s == 'e' = (ss, E)
    | s == 'w' = (ss, W)
    | s == 's' = case head ss of
        'e' -> (tail ss, SE)
        'w' -> (tail ss, SW)
    | s == 'n' = case head ss of
        'e' -> (tail ss, NE)
        'w' -> (tail ss, NW)

parsePath :: String -> Path
parsePath str = 
    if null rest
        then [dir]
        else dir : parsePath rest
    where
        (rest, dir) = parseDirection str

parseInput :: String -> [Path]
parseInput = map parsePath . lines

{-
         [-1, 1] [ 0, 1]
    [-1, 0] [ 0, 0] [ 1, 0] 
         [ 0,-1] [ 1,-1]
-}

step :: Position -> Direction -> Position
step (x, y) dir = case dir of
    E  -> (x+1, y)
    W  -> (x-1, y)
    SE -> (x+1, y-1)
    SW -> (x, y-1)
    NE -> (x, y+1)
    NW -> (x-1, y+1)

identify :: Path -> Position
identify = foldl step (0,0)

flipTile :: Record -> Position -> Record
flipTile record pos = 
    if Set.member pos record
        then Set.delete pos record
        else Set.insert pos record

main :: IO ()
main = do
    input <- readFile "input.txt"
    print . length
          . foldl flipTile Set.empty 
          . map identify
          . parseInput $ input
